if not qxnetlib then
	qxnetlib = {};
	require("cocos.framework.components.event"):bind(qxnetlib);    
	qxnetlib.CLIENT_PK_SIGN  = 0x55AA
	qxnetlib._host = "127.0.0.1";
	qxnetlib._port = 7000;
	qxnetlib._tcp = nil;
	qxnetlib.needTryConnectTime = 5
	qxnetlib._failReConnectTime = 5;	
	qxnetlib.sendfailTime = 0
	qxnetlib.reConnectTime = 2;	--设置重连的计划时间，如果为0则不需要重连，单位为s, ms = s / 1000
	qxnetlib._recvScheduler = nil;	--接收数据的桢事件
	qxnetlib._reConnectScheduler = nil;	--重连事件
	qxnetlib.EVENT_SERVER_CONNECTED = "EVENT_SERVER_CONNECTED";	--连接成功的事件
	qxnetlib.EVENT_SERVER_RECONNECTED = "EVENT_SERVER_RECONNECTED";	--连接成功的事件
	qxnetlib.EVENT_SERVER_CONNECT_FAIL = "EVENT_SERVER_CONNECT_FAIL";	--连接失败的事件
	qxnetlib.EVENT_TRY_RECONNECTED = "EVENT_TRY_RECONNECTED";	--重新连接失败的事件
	qxnetlib.EVENT_TRY_C_RECONNECTED = "EVENT_TRY_C_RECONNECTED";	--重新连接失败的事件
	qxnetlib.EVENT_SOCKET_CLOSED = "EVENT_SOCKET_CLOSED";	--连接断开的事件
	qxnetlib.EVENT_SOCKET_REVC_DATA = "EVENT_SOCKET_REVC_DATA";	--接收到数据的事件
	qxnetlib._recvDataCash = {};	--缓存数据块
	qxnetlib._encodeKey = "*(H#@@HJgnj&^fjdk556dede48^@g";	--加密秘钥
end
local scheduler = cc.Director:getInstance():getScheduler()
local protocol = require("gamemodel.protocol")
require("socket.core")
local socket = require("socket");
local qxpacket = require("net.qxpacket");
local QueryExit = appdf.req(appdf.CLIENT_SRC.."app.views.layer.other.QueryDialog")
local nRand = 661

qxnetlib.connectServer = function(host, port)
	if host then qxnetlib._host = host; end
	if port then qxnetlib._port = port; end
	qxnetlib._failReConnectTime = qxnetlib.needTryConnectTime
	print("connectServer",host, port)
	if not qxnetlib._tcp then
		qxnetlib._tcp = socket.tcp();
		qxnetlib._tcp:settimeout(0);
		qxnetlib._tcp:connect(qxnetlib._host, qxnetlib._port);
	end
	qxnetlib._doConnect()
end

qxnetlib._tryConnectServer = function()
	print("_tryConnectServer>>>>",qxnetlib._failReConnectTime,qxnetlib._host,qxnetlib._port)
	if qxnetlib._doConnect() then
		--连接成功，进入循环接收信息状态
		qxnetlib._failReConnectTime = qxnetlib.needTryConnectTime
	else		
		qxnetlib.authack = false
		if qxnetlib._failReConnectTime <= 0 then
			qxnetlib:dispatchEvent({name = qxnetlib.EVENT_SERVER_CONNECT_FAIL});	--抛出连接失败的事件
			-- if qxnetlib._reConnectScheduler then
			-- 	print("_doConnect  unscheduleScriptEntry>>>>")
			-- 	scheduler:unscheduleScriptEntry(qxnetlib._reConnectScheduler);
			-- 	qxnetlib._reConnectScheduler = nil;
			-- 	qxnetlib.disconect = true
			-- 	-- qxnetlib._onClose();
			-- end
		else
			--连接失败，设置重连计划
			qxnetlib._failReConnectTime = qxnetlib._failReConnectTime - 1
			qxnetlib._reConnectServer();
		end
	end
end

qxnetlib._reConnectServer = function()
	if not qxnetlib._tcp then
		qxnetlib._tcp = socket.tcp();
		qxnetlib._tcp:settimeout(0);
		qxnetlib._tcp:connect(qxnetlib._host, qxnetlib._port);   ---
	end
	if not qxnetlib._reConnectScheduler then
		qxnetlib._failReConnectTime = qxnetlib.needTryConnectTime
		qxnetlib._reConnectScheduler = scheduler:scheduleScriptFunc(qxnetlib._tryConnectServer, qxnetlib.reConnectTime ,false);
	end
end

qxnetlib._doConnect = function()
	if not  qxnetlib._tcp then
		return
	end
	local succ, status = qxnetlib._tcp:connect(qxnetlib._host, qxnetlib._port);
	print("_doConnect>>>>>", status)
	if status == "already connected" or status == "Operation already in progress" then
	-- local canread = socket.select({qxnetlib._tcp}, nil, 0)
	-- dump(canread,"canread>>>>>")
	-- print("_doConnect>>>>>", status)
	-- if canread and #canread > 0 then
		local isdirty = qxnetlib._tcp:dirty()
		if isdirty  then
			qxnetlib._onClose()
			local runScene = cc.Director:getInstance():getRunningScene()
			showToast(runScene,"_doConnect ditry",2)
			return
		end
		-- qxnetlib._recvDataCash = {}
		if qxnetlib.disconect then
			qxnetlib:dispatchEvent({name = qxnetlib.EVENT_SERVER_RECONNECTED});	--抛出重新连接成功的事件
		end
		if qxnetlib._reConnectScheduler then
			print("_doConnect connected unscheduleScriptEntry>>>>")
			scheduler:unscheduleScriptEntry(qxnetlib._reConnectScheduler);
			qxnetlib._reConnectScheduler = nil;
		end
		qxnetlib.disconect = false
		qxnetlib._setRecvCallBackInFrame();
		return true;
	elseif status == "closed" and qxnetlib._failReConnectTime <= 0 then
		print("qxnetlib._failReConnectTime>>>>",qxnetlib._failReConnectTime)
		qxnetlib.authack = false
		qxnetlib._recvDataCash = {};
		if qxnetlib._failReConnectTime <= 0 then
			qxnetlib.disconect = true
			qxnetlib._onClose()
			qxnetlib.connectServer(qxnetlib._host,qxnetlib._port)
		end
		if qxnetlib._reConnectScheduler then
			print("_doConnect closed  unscheduleScriptEntry>>>>")
			scheduler:unscheduleScriptEntry(qxnetlib._reConnectScheduler);
			qxnetlib._reConnectScheduler = nil;
		end
	else
		qxnetlib:dispatchEvent({name = qxnetlib.EVENT_TRY_RECONNECTED});
		qxnetlib._recvDataCash = {};
		qxnetlib._reConnectServer ()
	end
	return false;
end

local max_proc_count = 0;
local cur_proc_count = 0;

qxnetlib._onRecvCallBack = function()
	if qxnetlib.disconect  then
		print("_onRecvCallBack","连接已经断开")
		return
	end
	qxnetlib._onRecvBuffCallBack()
	-- xpcall(qxnetlib._onRecvBuffCallBack, function(error)
	-- 	print("_onRecvCallBack error>>>>>",error)
	-- end)
end

--桢函数
qxnetlib._onRecvBuffCallBack = function()
	-- print("_onRecvCallBack>>>>>>>>>>>1",os.time())
	local canread={}
	canread = socket.select({qxnetlib._tcp}, nil, 0)
	if #canread < 1 then
		return
	end
	-- print("_onRecvCallBack>>>>>>>>>>>2",canread,os.time())
	
	local body, status, partial 
	xpcall(function( ... )
		body, status, partial = qxnetlib._tcp:receive("*a");
	end, function(error)
		status = "closed"
		print("qxnetlib._tcp:receive error>>>>>",error)
	end)
	-- print("socket.select>>>>>>>>>>", status,body and #body or 0, #partial,#canread)
	if status == "closed" or status == "Socket is not connected" or (#canread > 0 and partial and #partial == 0) then
		
		dump(canread,"canread>>>>>")
		-- qxnetlib:dispatchEvent({name = qxnetlib.EVENT_SERVER_CONNECT_FAIL});	--抛出连接失败的事件
		--连接断开了
		print("_onRecvCallBack:close")
		print("_onRecvData:close"..#qxnetlib._recvDataCash)
		qxnetlib.disconect = true
		qxnetlib._onClose();
		if qxnetlib._failReConnectTime > 0 then	--尝试重连
			qxnetlib._tryConnectServer();
		else
			qxnetlib._pauseRecv()
		end
		return;
	end

	if (body and body:len() == 0) or (partial and partial:len() == 0) then
		--正常情况
		return;
	end
	--接收到数据，可能是数据库的片段
	if body and partial then body = body .. partial; end
	--print(body, partial, partial:len())
	-- print("_onRecvCallBack>>>>>>>>",#partial)
	table.insert(qxnetlib._recvDataCash, partial or body);
	-- local buffstr = readSocketData(partial or body);
	qxnetlib._onRecvData();
	print("qxnetlib._onRecvData")	
end


local headpacksize = 12
--处理接收到的数据缓存
qxnetlib._onRecvData = function()

	if #qxnetlib._recvDataCash < 1  then
		return;
	end
	local recvStr = table.concat(qxnetlib._recvDataCash);
	if  #recvStr < headpacksize then
		return;
	end
	
	local  _,wSign = string.unpack(recvStr:sub(1, 2), "=H") --buff:readShort()

	if wSign ~= 0x55AA then
		qxnetlib._recvDataCash = {};
		for i=3,#recvStr,2 do
			local  _,sign = string.unpack(recvStr:sub(i, i+1), "=H") --buff:readShort()
			if sign == 0x55AA then
				local leftDataStr = recvStr:sub(i, #recvStr);
				if leftDataStr and tostring(leftDataStr) ~= "" then
					table.insert(qxnetlib._recvDataCash, leftDataStr);
					return
				end
			end
		end
		return;
	end

	local _, recvLen = string.unpack(recvStr:sub(9,10), "=H");

	if recvLen < 0 then
		qxnetlib._onClose()
	end

	if recvLen + headpacksize > recvStr:len() then
		return;	--还没接收完成
	end

	local  _,wRecvCheckSum = string.unpack(recvStr:sub(3, 4), "=H") 
	local  _,wCtrl = string.unpack(recvStr:sub(5, 6), "=H")  --buff:readShort()
	local  _,wMsgID = string.unpack(recvStr:sub(7, 8), "=H")  --buff:readShort()
	local  _,wParam = string.unpack(recvStr:sub(11, 12), "=H") 
	local buff = recvStr:sub(13, recvLen+headpacksize)
	local wCheckSum = crc16Data(recvStr:sub(9, headpacksize+recvLen),recvLen+4)

	if 2018 == wMsgID then
		a =1
	end

	-- print("_onRecvData json string >>>>",buffstr)
	if wSign ~= 0x55AA then
		local runScene = cc.Director:getInstance():getRunningScene()
		local buff = recvStr:sub(13, recvLen+12)
		QueryExit:create("校验wSign错误  wSign:"..wSign.." recvLen:"..recvLen.." \n"..buffstr, function (bReTry) end)
		:setCanTouchOutside(false)
		:addTo(runScene)
	end


	print("_onRecvData>>>>>>",wSign==0x55AA , wRecvCheckSum==wCheckSum)
	local buffstr = ""
	if #buff > 0 then
		buffstr = DeCode(buff, recvLen);
	end
	
	if wRecvCheckSum ~= wCheckSum then
		local runScene = cc.Director:getInstance():getRunningScene()
		local buff = recvStr:sub(13, recvLen+12)
		QueryExit:create("checksum错误  wCheckSum:"..wCheckSum.."  wRecvCheckSum:"..wRecvCheckSum.."   wParam:"..wParam.." recvLen:"..recvLen.." \n"..buffstr, function (bReTry) end)
		:setCanTouchOutside(false)
		:addTo(runScene)
		-- return
	end

	print("_onRecvData>>>>",wSign,wCtrl,os.clock(),wMsgID,recvLen,buffstr)
	if buffstr == "null" then
		buffstr = {msg="客户端发送 参数错误  请检查发送协议的参数是否正确"}
	-- elseif  wMsgID == protocol.SM_GAME_STRUCT_MESSAGE then
	-- 	a=1
	-- 	local buffpack = qxpacket.new();
	-- 	buffpack:setPack(buffstr)
	-- 	local player_id = buffpack:readInt()
	-- 	local len = buffpack:readInt()
	-- 	local buflen = buffpack:readInt()
	-- 	local szNickName = buffpack:readStringLen(len,buflen-len)
	-- 	local id = buffpack:readInt()
	-- 	a=1
	-- 	local buffcheck = qxpacket.new();
	-- 	buffcheck:writeInt(fishid)
	-- 	buffcheck:writeInt(pathid)
	-- 	buffcheck:writeInt()
	-- 	buffcheck:writeStringLen(szNickName,len,buflen-len)
	-- 	buffcheck:writeInt(id)
	-- 	qxnetlib.sendStruct(protocol.CTRL_CLIENT_CLUSTER,207,buffcheck:getPack())

	else
		if buffstr ~= "" then
			xpcall(
				function( ... )
					buffstr = cjson.decode(buffstr)
				end,
				function( ... )
					local runScene = cc.Director:getInstance():getRunningScene()
					QueryExit:create("recvLen:"..string.len(buff).." / wSign:"..wSign..
					" / wRecvCheckSum:"..wRecvCheckSum.." / wCheckSum:"..wCheckSum.."  /  "..wMsgID, function (bReTry)
					end)
					:setCanTouchOutside(false)
					:addTo(runScene)
					-- buffstr = {}
				end
			)
		end
		wMsgID = buffstr.msgid or wMsgID
	end

	local leftDataStr = recvStr:sub(headpacksize + recvLen + 1, #recvStr);
	qxnetlib._recvDataCash = {};
	if leftDataStr and tostring(leftDataStr) ~= "" then
		table.insert(qxnetlib._recvDataCash, leftDataStr);
	end

	if qxnetlib.onRecvBuff then
		if wMsgID == nil then
			print("sdfasdf")
		end
		
		qxnetlib.onRecvBuff(wCtrl,wMsgID,buffstr);
	else
		print("未注册回调方法")
	end
	buff = nil;

	--检查包里是否还有数据
	if #qxnetlib._recvDataCash > 0 then		
		qxnetlib._onRecvData();
	end
end


qxnetlib._setRecvCallBackInFrame = function()
	--连接成功了，需要设置一个检查接收数据包的桢函数
	qxnetlib:dispatchEvent({name = qxnetlib.EVENT_SERVER_CONNECTED});	--抛出连接成功的事件
	if qxnetlib._recvScheduler then	--清除旧值
		scheduler:unscheduleScriptEntry(qxnetlib._recvScheduler);
		qxnetlib._recvScheduler = nil;
	end
	qxnetlib.tickcount = 1
	qxnetlib._recvScheduler = scheduler:scheduleScriptFunc( qxnetlib._onRecvCallBack , 0.1,false);
end

qxnetlib._resumeRecv = function() 
	if not qxnetlib._recvScheduler  then
		qxnetlib._recvScheduler = scheduler:scheduleSccriptFunc(qxnetlib._onRecvCallBack, 0.1,false);
	end
end

qxnetlib._pauseRecv = function()
	if qxnetlib._recvScheduler then
		scheduler:unscheduleScriptEntry(qxnetlib._recvScheduler);
		qxnetlib._recvScheduler = nil;
		-- qxnetlib:removeAllEventListenersForEvent(qxnetlib.EVENT_SERVER_CONNECTED);
	end
end

qxnetlib._onClose = function()
	-- print(debug.traceback( "_onClose",2))
	qxnetlib._recvDataCash = {}
	if qxnetlib._tcp then
		qxnetlib._tcp:close();
		qxnetlib._tcp = nil;
		qxnetlib.authack =  false
		qxnetlib:dispatchEvent({name = qxnetlib.EVENT_SOCKET_CLOSED});
	end
	if qxnetlib._recvScheduler then
		scheduler:unscheduleScriptEntry(qxnetlib._recvScheduler);
		qxnetlib._recvScheduler = nil;
	end
	if qxnetlib._reConnectScheduler then
		scheduler:unscheduleScriptEntry(qxnetlib._reConnectScheduler);
		qxnetlib._reConnectScheduler = nil;
	end	

end

qxnetlib.disConnection = function()
	qxnetlib._onClose()
end

qxnetlib.onCloseSocket = function()
	qxnetlib._onClose()
end

if not qxnetlib.cmdlib then
    qxnetlib.cmdlib = {};
end

if not qxnetlib.cmdHandler then
    qxnetlib.cmdHandler = {};
end

qxnetlib.regCmd = function(cmd, callback)
	assert(cmd);
	assert(callback);
	--assert(not cmdlib.cmdHandler[cmd], tostring(cmd) .. "exists");
    qxnetlib.cmdHandler[cmd] = function(buff)
        callback(buff);
    end
end


qxnetlib.send = function(wCtrl,wMsgID,bodyStr,bForceSend)
	if not qxnetlib.authack and not bForceSend then
		print("未认证消息>>>>>>>>>")
		return
	end
	if not qxnetlib._tcp then
		qxnetlib._reConnectServer()
		return
	end
	qxnetlib.checkParams()
	print("qxnetlib._tcp>>>>>>>",type(qxnetlib),type(qxnetlib) == socket.tcp())
	print("qxnetlib.send>> wCtrl:",wCtrl,"  wMsgID:",wMsgID,"  bodyStr:",bodyStr)
	assert(qxnetlib._tcp, "不存在连接实例");	
	local buffHead = qxpacket.new();
	buffHead:writeShort(qxnetlib.CLIENT_PK_SIGN);
	local tcpsend
	local buffcheck = qxpacket.new();
	if bodyStr and #bodyStr > 0 then
		bodyStr = EnCode(bodyStr,#bodyStr);
		buffcheck:writeShort(#bodyStr);	
		buffcheck:writeShort(nRand);
		local wCheckSum = crc16Data(buffcheck:getPack().. bodyStr,buffcheck:getLen()+#bodyStr)
		buffHead:writeShort(wCheckSum);
		buffHead:writeShort(wCtrl);	
		buffHead:writeShort(wMsgID);
		tcpsend = qxnetlib._tcp:send(buffHead:getPack() ..buffcheck:getPack().. bodyStr);
	else
		buffcheck:writeShort(0);	
		buffcheck:writeShort(nRand);
		local wCheckSum = crc16Data(buffcheck:getPack(),buffcheck:getLen())
		buffHead:writeShort(wCheckSum);
		buffHead:writeShort(wCtrl);	
		buffHead:writeShort(wMsgID);
		tcpsend =  qxnetlib._tcp:send(buffHead:getPack() ..buffcheck:getPack());
	end	
	
	
	print("sendlen>>>",tcpsend,wMsgID,bodyStr and #bodyStr or 0)
	-- buffHead:setPackSize(buffBody:getLen() + buffHead:getLen());

	if not tcpsend or tcpsend < 0 then
		qxnetlib.sendfailTime = qxnetlib.sendfailTime + 1
		showToast(runScene,"send data failed",1)
		if qxnetlib.sendfailTime  > 2 then
			qxnetlib._tryConnectServer();
		end
	else
		qxnetlib.sendfailTime = 0
	end
	
	buffBody = nil;
	buffHead = nil;
end
-- STRUCT
qxnetlib.sendStruct = function(wCtrl,wMsgID,bodyStr,bForceSend)
	if not qxnetlib.authack and not bForceSend then
		print("未认证消息>>>>>>>>>")
		return
	end
	if not qxnetlib._tcp then
		qxnetlib._reConnectServer()
		return
	end
	qxnetlib.checkParams()
	print("qxnetlib._tcp>>>>>>>",type(qxnetlib),type(qxnetlib) == socket.tcp())
	print("qxnetlib.send>> wCtrl:",wCtrl,"  wMsgID:",wMsgID,"  bodyStr:",bodyStr)
	assert(qxnetlib._tcp, "不存在连接实例");	
	local buffHead = qxpacket.new();
	buffHead:writeShort(qxnetlib.CLIENT_PK_SIGN);
	local tcpsend
	local buffcheck = qxpacket.new();
	local bodylen = #bodyStr
	if bodyStr and bodylen > 0 then
		bodyStr = EnCode(bodyStr,bodylen);
		buffcheck:writeShort(bodylen);	
		buffcheck:writeShort(nRand);
		local wCheckSum = crc16Data(buffcheck:getPack().. bodyStr,buffcheck:getLen()+bodylen)
		buffHead:writeShort(wCheckSum);
		buffHead:writeShort(wCtrl);	
		buffHead:writeShort(wMsgID);
		tcpsend = qxnetlib._tcp:send(buffHead:getPack() ..buffcheck:getPack().. bodyStr);
	else
		buffcheck:writeShort(0);	
		buffcheck:writeShort(nRand);
		local wCheckSum = crc16Data(buffcheck:getPack(),buffcheck:getLen())
		buffHead:writeShort(wCheckSum);
		buffHead:writeShort(wCtrl);	
		buffHead:writeShort(wMsgID);
		tcpsend =  qxnetlib._tcp:send(buffHead:getPack() ..buffcheck:getPack());
	end	
	
	
	print("sendlen>>>",tcpsend,wMsgID,bodyStr and #bodyStr or 0)
	-- buffHead:setPackSize(buffBody:getLen() + buffHead:getLen());

	if not tcpsend or tcpsend < 0 then
		qxnetlib.sendfailTime = qxnetlib.sendfailTime + 1
		showToast(runScene,"send data failed",1)
		if qxnetlib.sendfailTime  > 2 then
			qxnetlib._tryConnectServer();
		end
	else
		qxnetlib.sendfailTime = 0
	end
	
	buffBody = nil;
	buffHead = nil;
end

function qxnetlib.checkParams( ... )
    nRand = nRand  + 1
	if nRand > 9999 then
		 nRand = 661
	end
end
function qxnetlib.isDisConnect( ... )
	return  qxnetlib.disconect
end

-- local ENCODE_DIVISOR = 0xAA;
-- function qxnetlib.DeCodeData(pb,len)

-- 	local lenpb = #pb
-- 	local a, b, c, d
-- 	local destr = ""
-- 	local buff = qxpacket.new();
-- 	a = ENCODE_DIVISOR;
-- 	for i = 13, #pb do
-- 		local byt = pb:sub(i,i+1)
-- 		b = string.unpack(byt, "=A"); --pb:sub(i,i+1)
-- 		print("DeCodeData1>>",b)
-- 		c = bit:_rshift(b,4) -- b >> 5;
-- 		d = bit:_lshift(b,3) -- b << 3;
-- 		local xor = bit:_xor(bit:_or(c,d),a) -- (c | d) ^ a;
-- 		buff:writeByte(xor)
-- 		print("DeCodeData2>>",xor,buff:readByte())
-- 		destr = destr..xor
-- 		a = b;
-- 	end
-- 	return destr
-- end

-- function qxnetlib.DeCodeData(pb,len)
-- 	local a, b, c, d
-- 	a = ENCODE_DIVISOR;
-- 	for i = 1, len do
-- 		b = pb[i]
-- 		c = bit.ashr(b,4) -- b >> 5;
-- 		d = bit.shl (b,3) -- b << 3;
-- 		pb[i] = bit.xor(bit.bor(c,d),a) -- (c | d) ^ a;
-- 		a = b;
-- 	end
-- 	return pb
-- end


return qxnetlib

